home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************\
-
- CMIO.cpp
-
- [Macintosh]
-
- Routines for doing A/D conversion with National Instruments
- NB-MIO-16 card.
- Written by Dan Crevier, 1994
-
- Usage:
- At startup:
- • Create a CMIO object (myMIO = new CMIO)
- • Call Config(). It will return true if there is an MIO
- board available, false if there isn't
-
- Each time you want to record some data:
- • Call ConfigureCollection() with the array of channels
- to scan, the interval in µs between samples, and
- the number of samples to record
- • Call StartCollection() to start the data collection
- • Call SampleAvailable() to see if a sample is available
- It can also return error codes kErrOverflow, kErrOverrun
- (or kErrOverflow + kOverrun). These are described on
- page 4-53 in the NB-MIO-16 User's manual (amoung other
- places)
- • Call GetSample() to return the sample. It will be in
- signed format
-
- \*********************************************************************/
-
- #include <slots.h>
- #include <string.h>
- #include "CMIO.h"
-
- #define macSlotNum(s) (s+8) /* slot translation */
- #define GetBase24Address(s) (((long) (macSlotNum(s))) << 20)
- #define GetBase32Address(s) ((((long) (macSlotNum(s))) << 24) | 0xF0000000)
-
- // Make sure it doesn't optimize out any code that looks useless, like
- // writing different values to an MIO register in two consequtive
- // statements
-
- #pragma options(!global_optimizer)
-
- /*********************************************************************\
- Config - finds the MIO board and sets it up. Returns 1 if
- successful.
- \*********************************************************************/
-
-
- short CMIO::Config(void)
- {
- char mode = true32b;
- SpBlock mySpBlock;
- OSErr error;
- unsigned char name[128];
- short slot;
- unsigned char *slotBaseAddr;
- short ctr;
-
- // •• find MIO board ••
- for(slot=0; slot<8; slot++)
- {
- mySpBlock.spSlot=slot+8;
- error=SCkCardStat(&mySpBlock);
- if (error) continue;
- mySpBlock.spID=1;
- mySpBlock.spResult=(long) &name;
- error=SReadDrvrName(&mySpBlock);
- // name is a pascal string, so skip 1st character in conversion
- if (strncmp((char *)name+1, ".NB-MIO-16", 6)==0) break;
- }
- if (slot==8) return 0; // not found
-
- // •• set up register pointers ••
- SwapMMUMode(&mode);
- if(mode) // check for 32-bit addressing mode
- slotBaseAddr = (unsigned char *) GetBase32Address(slot);
- else // 24-bit mode
- slotBaseAddr = (unsigned char *) GetBase24Address(slot);
- SwapMMUMode(&mode); // restore mode
-
- // Configuration and Status Registers
- comReg1 = (unsigned short *)(slotBaseAddr + 0x00);
- comReg2 = (unsigned short *)(slotBaseAddr + 0x04);
- statReg = (unsigned short *)(slotBaseAddr + 0x00);
-
- // Event Strobe Register Group
- startConvReg = (unsigned short *)(slotBaseAddr + 0x10);
- startDAQReg = (unsigned short *)(slotBaseAddr + 0x14);
- ADClearReg = (unsigned short *)(slotBaseAddr + 0x18);
- exStrobeReg = (unsigned short *)(slotBaseAddr + 0x1C);
-
- // Analog Output Register Group
- DAC0Reg = (unsigned short *)(slotBaseAddr + 0x20);
- DAC1Reg = (unsigned short *)(slotBaseAddr + 0x24);
- DAC01Reg = (unsigned short *)(slotBaseAddr + 0x28);
-
- // Analog Input Register Group
- MUXCounterReg = (unsigned short *)(slotBaseAddr + 0x08);
- MUXGainReg = (unsigned short *)(slotBaseAddr + 0x0C);
- ADFIFOReg = (unsigned short *)(slotBaseAddr + 0x2C);
-
- // Counter/Timer (AM9513) Register Group
- AmDataReg = (unsigned short *)(slotBaseAddr + 0x30);
- AmCommandReg = (unsigned short *)(slotBaseAddr + 0x34);
- AmStatusReg = (unsigned short *)(slotBaseAddr + 0x34);
-
- // •• Reset board (NB-MIO-16 User's Manual page 4-36) ••
- *comReg1 = 0;
- *comReg2 = 0;
- *MUXGainReg = 0;
- *AmCommandReg = 0xFFFF;
- *AmCommandReg = 0xFFEF;
- *AmCommandReg = 0xFF17;
- *AmDataReg = 0xF000;
- for(ctr=1; ctr<=5; ctr++)
- {
- *AmCommandReg = 0xFF00 + ctr;
- *AmDataReg = 0x0004;
- *AmCommandReg = 0xFF08 + ctr;
- *AmDataReg = 0x0003;
- }
- *AmCommandReg = 0xFF5F;
-
- *ADClearReg = 0;
-
- comRegVal = 0;
-
- return 1;
- }
-
- /*********************************************************************\
- ConfigureCollection -- set up the MIO to do Multiple A/D
- conversions with Channel Scanning
- NB-MIO-16 User's manual page 4-49
- The channelArray is an array of 16 channel numbers (0-15) to sample
- a gain of 1 is used
- sampleInterval is the time between samples in units of 1 µs
- (2-65535)
- nSamples is the number of samples to take
- \*********************************************************************/
-
- void CMIO::ConfigureCollection(unsigned short *channelArray, unsigned short sampleInterval,
- unsigned long nSamples)
- {
- short i;
-
- // clear before starting
- *ADClearReg = 0;
-
- // •• Set up the analog channel and gain selection sequence ••
- for(i=0; i<15; i++)
- {
- *MUXCounterReg = i;
- *MUXGainReg = channelArray[i];
- }
- *MUXCounterReg = 15;
- *MUXGainReg = channelArray[15] + 0x0010; // from MIO Control App
-
- // •• Program the sample-interval counter ••
- *AmCommandReg = 0xFF03;
- *AmDataReg = 0x8B25; // 1 MHz clock
- *AmCommandReg = 0xFF0B;
- *AmDataReg = 0x0002;
- *AmCommandReg = 0xFF44;
- *AmCommandReg = 0xFFF3;
- *AmCommandReg = 0xFF0B; // from MIO Control App
- *AmDataReg = sampleInterval;
- *AmCommandReg = 0xFFF3; // from MIO Control App
- *AmCommandReg = 0xFFF3; // from MIO Control App
- *AmCommandReg = 0xFF24;
-
- // •• Program the sample counter ••
- if (nSamples<=65536)
- {
- if (nSamples==65536) nSamples = 0;
- *AmCommandReg = 0xFF04;
- *AmDataReg = 0x1021;
- *AmCommandReg = 0xFF0C;
- *AmDataReg = (unsigned short)nSamples;
- *AmCommandReg = 0xFF68;
- comRegVal = 0;
- }
- else
- {
- *AmCommandReg = 0xFF04;
- *AmDataReg = 0x1001;
- *AmCommandReg = 0xFF0C;
- *AmDataReg = nSamples & 0xFFFFL;
- *AmCommandReg = 0xFF48;
- *AmDataReg = 0x0000;
- *AmCommandReg = 0xFF28;
- *AmCommandReg = 0xFF05;
- *AmDataReg = 0x0001;
- *AmCommandReg = 0xFF0D;
- *AmDataReg = (nSamples >> 16) + 1;
- *AmCommandReg = 0xFF70;
- comRegVal = k1632CNT;
- }
- // •• Clear the A/D circuitry and reset the mux counter ••
- *ADClearReg = 0;
- *MUXCounterReg = 0;
-
- }
-
- /*********************************************************************\
- StartCollection - start collecting data. Call after calling
- ConfigureCollection()
- \*********************************************************************/
-
- void CMIO::StartCollection(void)
- {
- // enable scanning
- comRegVal |= kDAQEN;
- comRegVal |= kSCANEN;
- *comReg1 = comRegVal;
- // start scanning
- *startDAQReg = 0;
- }
-
- /*********************************************************************\
- SampleAvailable - returns true if a sample is available
- Also checks for an error in the status register.
- Check (error & kErrOverflow) and (error & kErrOverrun)
- (both can be set)
- \*********************************************************************/
-
- short CMIO::SampleAvailable(short *error)
- {
- short status;
-
- status = *statReg;
- *error = status & (kErrOverrun + kErrOverflow);
-
- return (status & kCONVAVAIL);
- }
-
- /*********************************************************************\
- EndCollection - resets clocks after collection
- \*********************************************************************/
-
- void CMIO::EndCollection(void)
- {
- // •• Reset counter 3
- *AmCommandReg = 0xFFC4;
- *AmCommandReg = 0xFF03;
- *AmDataReg = 0x0004;
- *AmCommandReg = 0xFF0B;
- *AmDataReg = 0x0003;
- *AmCommandReg = 0xFF44;
- *AmCommandReg = 0xFF44;
-
- // •• Reset counter 4
- *AmCommandReg = 0xFFC8;
- *AmCommandReg = 0xFF04;
- *AmDataReg = 0x0004;
- *AmCommandReg = 0xFF0C;
- *AmDataReg = 0x0003;
- *AmCommandReg = 0xFF48;
- *AmCommandReg = 0xFF48;
-
- // •• Reset counter 3
- *AmCommandReg = 0xFFD0;
- *AmCommandReg = 0xFF05;
- *AmDataReg = 0x0004;
- *AmCommandReg = 0xFF0D;
- *AmDataReg = 0x0003;
- *AmCommandReg = 0xFF50;
- *AmCommandReg = 0xFF50;
-
- *ADClearReg = 0;
-
- comRegVal = 0;
- }
-